﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PMCT
{
    public partial class ViewGantt : Form
    {
        public ConfigRoot curRoot;
        public int[,] adj;
        public int[] inDegree;
        public int[] outDegree;
        public List<string> preJobs = null;
        public int[] level;

        public ViewGantt()
        {
            InitializeComponent();
        }

        private void ViewGantt_Load(object sender, EventArgs e)
        {
            //this.Size = this.Parent.Size;

            Rebuild();

            ShowGantt();

            CheckGraph();

            try
            {
                if (selectedItems.Count != 0)
                    tabControl1.SelectedIndex = 1;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

        private void Rebuild()
        {
            int cnt = curRoot.listItem.Count;
            adj = new int[cnt, cnt];
            inDegree = new int[cnt];
            outDegree = new int[cnt];
            preJobs = new List<string>(cnt);
            for (int i = 0; i < cnt; i++)
                preJobs.Add("");
            level = new int[cnt];

            // build
            for (int i = 0; i < cnt; i++)
            {
                for (int j = 0; j < curRoot.listItem.Count; j++)
                {
                    if (i != j && Match(curRoot.listItem[i].output, curRoot.listItem[j].input))
                    {
                        adj[i, j] = 1;
                        inDegree[j]++;
                        outDegree[i]++;

                        if (preJobs[j] == "")
                            preJobs[j] += (i + 1).ToString();
                        else
                            preJobs[j] += "," + (i + 1).ToString();

                        if (level[j] < level[i] + 1)
                            level[j] = level[i] + 1;
                    }
                }
            }
        }

        private void ShowGantt()
        {
            listView1.Items.Clear();
            listView1.Columns.Clear();

            // show
            ColumnHeader ch1 = new ColumnHeader();
            ch1.Text = "编号";
            ch1.Width = 50;
            listView1.Columns.Add(ch1);

            ColumnHeader ch2 = new ColumnHeader();
            ch2.Text = "名称";
            ch2.Width = 220;
            listView1.Columns.Add(ch2);

            ColumnHeader ch3 = new ColumnHeader();
            ch3.Text = "前置任务";
            ch3.Width = 100;
            listView1.Columns.Add(ch3);

            ListViewItem lvi;
            ListViewItem.ListViewSubItem lvsi;

            int cnt = 0;
            foreach (Item item in curRoot.listItem)
            {
                lvi = new ListViewItem();
                lvi.Text = (cnt + 1).ToString();

                lvsi = new ListViewItem.ListViewSubItem();
                lvsi.Text = item.name;
                lvi.SubItems.Add(lvsi);

                lvsi = new ListViewItem.ListViewSubItem();
                lvsi.Text = preJobs[cnt];
                lvi.SubItems.Add(lvsi);

                listView1.Items.Add(lvi);
                cnt++;
            }
        }

        private bool CheckGraph()
        {
            bool checkInDegree = false;
            for (int i = 0; i < curRoot.listItem.Count; i++)
            {
                if (inDegree[i] == 0)
                {
                    checkInDegree = true;
                    break;
                }
            }
            if (checkInDegree == false)
            {
                System.Windows.Forms.MessageBox.Show("该流程图的所有入度为零，流程图无效，请检查！");
            }

            bool checkOutDegree = false;
            for (int i = 0; i < curRoot.listItem.Count; i++)
            {
                if (outDegree[i] == 0)
                {
                    checkOutDegree = true;
                    break;
                }
            }
            if (checkOutDegree == false)
            {
                System.Windows.Forms.MessageBox.Show("该流程图的所有出度为零，流程图无效，请检查！");
            }

            return false;
        }

        private bool Match(List<Guid> g1, List<Guid> g2)
        {
            foreach (Guid g in g1)
            {
                foreach (Guid gg in g2)
                {
                    if (g == gg)
                        return true;
                }
            }
            return false;
        }

        public Rectangle[] rectlist;

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (curRoot.listItem.Count == 0)
                return;

            Graphics g = e.Graphics;
            int w = e.ClipRectangle.Width;
            int factor = w / curRoot.listItem.Count;

            int rectHeight = 18;
            int rectWidth = factor;// 30;
            int rowInterval = 8;
            int colInterval = 10;
            int unitHeight = rectHeight + rowInterval;
            int unitWidth = rectWidth + colInterval;

            rectlist = new Rectangle[curRoot.listItem.Count];

            for (int i = 0; i < curRoot.listItem.Count; i++)
            {
                Point centerPoint = new Point((level[i] + 1) * unitWidth - unitWidth / 2, (i + 1) * unitHeight - unitHeight / 2);
                Rectangle rect = new Rectangle(centerPoint.X - rectWidth / 2, centerPoint.Y - rectHeight / 2, rectWidth, rectHeight);

                // draw rect
                g.FillRectangle(Brushes.Blue, rect);
                Color clr = Color.LightBlue;
                if (selectedItems.Contains(i))
                {
                    clr = Color.Red;
                }
                g.DrawLine(new Pen(clr, 2), new Point(rect.Left, rect.Bottom), new Point(rect.Right, rect.Bottom));
                g.DrawLine(new Pen(clr, 2), new Point(rect.Right, rect.Top), new Point(rect.Right, rect.Bottom));
                rectlist[i] = rect;

                // show name
                string name = curRoot.listItem[i].name;
                if (name.Length > 8)
                    name = name.Substring(0, 8);
                //g.DrawString((i + 1).ToString(),
                g.DrawString(name,
                    new Font("宋体", 9),
                    Brushes.White,
                    new Point(rect.Left + 1, rect.Top + 1));

                // draw line
                for (int j = 0; j < curRoot.listItem.Count; j++)
                {
                    if (adj[i, j] == 1)
                    {
                        Pen pen = new Pen(Brushes.Black, 2);
                        int newX = centerPoint.X + unitWidth / 2 + (level[j] - level[i] - 1) * unitWidth + colInterval;
                        g.DrawLine(pen, new Point(centerPoint.X + rectWidth / 2, centerPoint.Y), new Point(newX, centerPoint.Y));

                        int newY = centerPoint.Y + (j - i) * unitHeight - rectHeight / 2;
                        g.DrawLine(pen, new Point(newX, centerPoint.Y), new Point(newX, newY));

                        int arrow = 5;
                        g.DrawLine(pen, new Point(newX, newY), new Point(newX + arrow, newY - arrow));
                        g.DrawLine(pen, new Point(newX, newY), new Point(newX - arrow, newY - arrow));
                    }
                }
            }
        }

        private ToolTip curTooltip = new ToolTip();
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (rectlist == null)
                return;

            bool flag = false;

            Point p = new Point(e.X, e.Y);
            for (int i = 0; i < rectlist.GetLength(0); i++)
            {
                if (rectlist[i].Contains(p))
                {
                    if (!curTooltip.Active)
                    {
                        string tip = "名称:" + curRoot.listItem[i].name;

                        foreach (Dimension d in curRoot.listDimension)
                        {
                            List<int> all = new List<int>();
                            bool found = FormMain.FindMatchAllGuid(d.list, curRoot.listItem[i].dimension, all);
                            if (found == true)
                            {
                                tip += "\n";
                                tip += d.name + ":";

                                string str = "";
                                bool isFirst = true;
                                foreach (int j in all)
                                {
                                    if (!isFirst)
                                        str += ", ";
                                    str += d.list[j].name;
                                    isFirst = false;
                                }
                                tip += str;
                            }
                        }

                        curTooltip.SetToolTip(pictureBox1, tip);
                        curTooltip.Active = true;
                    }

                    flag = true;
                    break;
                }
            }

            if (flag == false)
                curTooltip.Active = false;
        }

        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && e.Clicks == 1)
            {
                Point p = new Point(e.X, e.Y);
                for (int i = 0; i < rectlist.GetLength(0); i++)
                {
                    if (rectlist[i].Contains(p))
                    {
                        ItemForm f = new ItemForm();
                        f.curRoot = (ConfigRoot)curRoot.Clone();
                        f.curItem = (Item)curRoot.listItem[i].Clone();
                        if (f.ShowDialog() == DialogResult.OK)
                        {
                            curRoot.listItem[i] = (Item)f.curItem.Clone();

                            Rebuild();
                            ShowGantt();
                            CheckGraph();
                        }

                        pictureBox1.Invalidate();
                        break;
                    }
                }
            }
        }

        public List<int> selectedItems = new List<int>();
        private void button2_Click(object sender, EventArgs e)
        {
            InputBox ib = new InputBox();
            DialogResult dr = ib.ShowDialog();
            if (dr == DialogResult.OK)
            {
                selectedItems.Clear();
                if (ib.inputText != null && ib.inputText != "")
                {
                    SmartFind(curRoot, ib.inputText, selectedItems);
                }
            }

            pictureBox1.Invalidate();
        }

        public static void SmartFind(ConfigRoot root, string tag, List<int> results)
        {
            for (int cnt = 0; cnt < root.listItem.Count; cnt++)
            {
                // name
                if (root.listItem[cnt].name.Contains(tag))
                {
                    results.Add(cnt);
                    continue;
                }

                // dimension
                bool foundFlag = false;
                foreach (Dimension d in root.listDimension)
                {
                    List<int> foundIndex = new List<int>();
                    if (FormMain.FindMatchAllGuid(d.list, root.listItem[cnt].dimension, foundIndex) == true)
                    {
                        foreach (int idx in foundIndex)
                        {
                            if (d.list[idx].name.Contains(tag))
                            {
                                results.Add(cnt);
                                foundFlag = true;
                                break;
                            }
                        }

                        if (foundFlag)
                            break;
                    }
                }
                if (foundFlag)
                    continue;

                // unit
            }
        }
    }
}
